﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;
namespace YueDa.Web.Common
{
    public static class ConvertToDataTable
    {
        ///// <summary>
        ///// DataGridView 转成DataTable 针对于某些特定的绑定
        ///// </summary>
        ///// <param name="dgv"></param>
        ///// <returns></returns>
        //public DataTable GetDgvToTable(System.Windows.Forms.DataGridView dgv)
        //{
        //    DataTable dt = new DataTable();
        //    for (int count = 0; count < dgv.Columns.Count; count++)
        //    {
        //        DataColumn dc = new DataColumn(dgv.Columns[count].Name.ToString());
        //        dt.Columns.Add(dc);
        //    }
        //    for (int count = 0; count < dgv.Rows.Count; count++)
        //    {
        //        DataRow dr = dt.NewRow();
        //        for (int countsub = 0; countsub < dgv.Columns.Count; countsub++)
        //        {
        //            dr[countsub] = Convert.ToString(dgv.Rows[count].Cells[countsub].Value);
        //        }
        //        dt.Rows.Add(dr);
        //    }
        //    return dt;
        //}

        public static DataTable iToDataTable<T>(List<T> list)
        {
            DataTable result = new DataTable();
            if (list.Count > 0)
            {
                PropertyInfo[] propertys = list[0].GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    result.Columns.Add(pi.Name, pi.PropertyType);
                }
                for (int i = 0; i < list.Count; i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in propertys)
                    {
                        object obj = pi.GetValue(list[i], null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    result.LoadDataRow(array, true);
                }
            }
            return result;
        }
        /// <summary>
        /// List 转成 DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="Entitys"></param>
        /// <returns></returns>
        public static DataTable ToDataTable<T>(List<T> Entitys)
        {
            //检查实体集合不能为空

            if (Entitys == null || Entitys.Count < 1)
            {
                throw new Exception("需转换的集合为空");
            }

            //取出第一个实体的所有Propertie
            //即构造出所有的列头名称
            Type entityType = Entitys[0].GetType();
            PropertyInfo[] entityProperties = entityType.GetProperties();
            DataTable dt = new DataTable();
            //添加列头
            for (int i = 0; i < entityProperties.Length; i++)
            {
                dt.Columns.Add(entityProperties[i].Name, entityProperties[i].PropertyType);
            }
            //将所有entity添加到DataTable中
            foreach (object entity in Entitys)
            {
                //检查所有的的实体都为同一类型

                if (entity.GetType() != entityType)
                {
                    throw new Exception("要转换的集合元素类型不一致");
                }
                object[] entityValues = new object[entityProperties.Length];
                for (int i = 0; i < entityProperties.Length; i++)
                {
                    //i=8 的这个类型无法通过反射得到，得到会有错误
                    if (i == 8)
                    {
                        entityValues[i] = null;
                    }
                    else
                    {
                        entityValues[i] = entityProperties[i].GetValue(entity, null);
                    }
                }
                dt.Rows.Add(entityValues);
            }
            return dt;
        }
        /// <summary>
        ///  objlist 转成DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objlist"></param>
        /// <returns></returns>
        public static DataTable Fill<T>(IList<T> objlist)
        {
            if (objlist == null || objlist.Count <= 0)
            {
                return null;
            }
            DataTable dt = new DataTable(typeof(T).Name);
            DataColumn column;
            DataRow row;

            System.Reflection.PropertyInfo[] myPropertyInfo = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (T t in objlist)
            {
                if (t == null)
                {
                    continue;
                }

                row = dt.NewRow();

                for (int i = 0, j = myPropertyInfo.Length; i < j; i++)
                {
                    System.Reflection.PropertyInfo pi = myPropertyInfo[i];

                    string name = pi.Name;

                    if (dt.Columns[name] == null)
                    {
                        column = new DataColumn(name, pi.PropertyType);
                        dt.Columns.Add(column);
                    }

                    row[name] = pi.GetValue(t, null);
                }

                dt.Rows.Add(row);
            }
            return dt;
        }

        //====表中无数据时使用:
        public static DataTable nullListToDataTable(IList list)
        {
            DataTable result = new DataTable();
            object temp;
            if (list.Count > 0)
            {
                PropertyInfo[] propertys = list[0].GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    //if (!(pi.Name.GetType() is System.Nullable))
                    if (pi != null)
                    {
                        //pi = (PropertyInfo)temp;  
                        result.Columns.Add(pi.Name, pi.PropertyType);
                    }
                }
                for (int i = 0; i < list.Count; i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in propertys)
                    {
                        object obj = pi.GetValue(list[i], null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    result.LoadDataRow(array, true);
                }
            }
            return result;
        }
        public static DataTable ConvertToDataSet<T>(IList<T> list)
        {
            if (list == null || list.Count <= 0)
            //return null;
            {
                DataTable result = new DataTable();
                object temp;
                if (list.Count > 0)
                {
                    PropertyInfo[] propertys = list[0].GetType().GetProperties();
                    foreach (PropertyInfo pi in propertys)
                    {
                        //if (!(pi.Name.GetType() is System.Nullable))
                        //if (pi!=null)
                        {
                            //pi = (PropertyInfo)temp;  
                            result.Columns.Add(pi.Name, pi.PropertyType);
                        }
                    }
                    for (int i = 0; i < list.Count; i++)
                    {
                        ArrayList tempList = new ArrayList();
                        foreach (PropertyInfo pi in propertys)
                        {
                            object obj = pi.GetValue(list[i], null);
                            tempList.Add(obj);
                        }
                        object[] array = tempList.ToArray();
                        result.LoadDataRow(array, true);
                    }
                }
                return result;
            }
            else
            {
                DataSet ds = new DataSet();
                DataTable dt = new DataTable(typeof(T).Name);
                DataColumn column;
                DataRow row;
                System.Reflection.PropertyInfo[] myPropertyInfo =
                    typeof(T).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
                foreach (T t in list)
                {
                    if (t == null) continue;
                    row = dt.NewRow();
                    for (int i = 0, j = myPropertyInfo.Length; i < j; i++)
                    {
                        System.Reflection.PropertyInfo pi = myPropertyInfo[i];
                        String name = pi.Name;
                        if (dt.Columns[name] == null)
                        {
                            if (pi.PropertyType.UnderlyingSystemType.ToString() == "System.Nullable`1[System.Int32]")
                            {
                                column = new DataColumn(name, typeof(Int32));
                                dt.Columns.Add(column);
                                //row[name] = pi.GetValue(t, new object[] {i});//PropertyInfo.GetValue(object,object[])
                                if (pi.GetValue(t, null) != null)
                                    row[name] = pi.GetValue(t, null);
                                else
                                    row[name] = System.DBNull.Value;
                            }
                            else
                            {
                                column = new DataColumn(name, pi.PropertyType);
                                dt.Columns.Add(column);
                                row[name] = pi.GetValue(t, null);
                            }
                        }
                    }
                    dt.Rows.Add(row);
                }
                ds.Tables.Add(dt);
                return ds.Tables[0];
            }
        }
        public delegate object[] CreateRowDelegate<T>(T t);

        static public DataTable toToDataTable<T>(this IEnumerable<T> varlist, CreateRowDelegate<T> fn)
        {

            DataTable dtReturn = new DataTable();

            // column names

            PropertyInfo[] oProps = null;

            // Could add a check to verify that there is an element 0

            foreach (T rec in varlist)
            {

                // Use reflection to get property names, to create table, Only first time, others will follow

                if (oProps == null)
                {

                    oProps = ((Type)rec.GetType()).GetProperties();

                    foreach (PropertyInfo pi in oProps)
                    {

                        Type colType = pi.PropertyType; if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
                        {

                            colType = colType.GetGenericArguments()[0];

                        }

                        dtReturn.Columns.Add(new DataColumn(pi.Name, colType));

                    }

                }

                DataRow dr = dtReturn.NewRow(); foreach (PropertyInfo pi in oProps)
                {

                    dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue(rec, null);

                }

                dtReturn.Rows.Add(dr);

            }

            return (dtReturn);

        }
    }
}
